/******************************************************
 Project:				PCSync
 Author:				jean-philippe
 File name:				Server.java
 Date created:			Aug 23, 2012
 Date last modified:	Aug 23, 2012
 *******************************************************
 Modification History
 *******************************************************
 Aug 23, 2012		Initial version.
 ******************************************************/
package pcsync.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Observable;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import pcsync.Config;

/**
 * @author jean-philippe
 *
 */
public class Server extends Observable implements Runnable
{
	private Logger logger;
	private ServerSocket serverSocket;
	private ArrayList<ClientConnection> clientConnections;
	private ArrayList<Thread> threads;
	private int state;
	private boolean active;
	
	public Server()
	{
		// Enable logging
		PropertyConfigurator.configure(Config.LOGGER_PROPERTIES_FILE);
		logger = Logger.getLogger(this.getClass().getCanonicalName());
		logger.info("Server initializing");
		
		setState(State.INITIALIZING);
		
		this.clientConnections = new ArrayList<ClientConnection>();
		this.threads = new ArrayList<Thread>();
		this.active = true;
	}
	
	private void setState(int state)
	{
		if(this.state != state)
		{
			this.state = state;
			setChanged();
			notifyObservers();
		}
	}
	
	public int getState()
	{
		return state;
	}
	
	public void stop()
	{
		active = false;
		logger.info("User has requested for the server to stop");
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run()
	{
		try
		{
			this.serverSocket = new ServerSocket(Config.SERVER_PORT);
		}
		catch (IOException e)
		{
			// TODO Auto-generated catch block
			logger.error("Unable to start server");
			e.printStackTrace();
		}
		logger.info("Listening on port " + Config.SERVER_PORT);
		setState(State.ACTIVE);
		
		// accept incoming client connections
		while( this.active )
		{
			try
			{
				Socket clientSocket = serverSocket.accept();
				ClientConnection client = new ClientConnection(clientSocket);
				this.clientConnections.add(client);
				
				Thread t = new Thread(client);
				t.setName(clientSocket.getInetAddress().getHostName());
				threads.add(t);
				t.start();
			}
			catch(IOException ioe)
			{
				logger.warn("An incoming connection request has failed");
				ioe.printStackTrace();
			}
		}
	}
}